// ///////////////////////////// MIT License //////////////////////////////////// //
//                                                                                //
// Copyright (c) 2010 David Zsolt Manrique                                        //
//                    david.zsolt.manrique@gmail.com                              //
//                                                                                //
// Permission is hereby granted, free of charge, to any person obtaining a copy   //
// of this software and associated documentation files (the "Software"), to deal  //
// in the Software without restriction, including without limitation the rights   //
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell      //
// copies of the Software, and to permit persons to whom the Software is          //
// furnished to do so, subject to the following conditions:                       //
//                                                                                //
// The above copyright notice and this permission notice shall be included in     //
// all copies or substantial portions of the Software.                            //
//                                                                                //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR     //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,       //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE    //
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER         //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  //
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN      //
// THE SOFTWARE.                                                                  //
//                                                                                //
// ////////////////////////////////////////////////////////////////////////////// //

#ifndef STRUCTURE_H
#define STRUCTURE_H

#include "potential_base.h"

//! parameter array types
struct params_t : std::vector<param_type>
{
};

//! Potential list type.
//! It calculates the total potential, total force.
struct potential_list_t
{
public:
	std::list<potential_base*> data;
public:
	//! Add new pointer to the list. Assumed that p is allocated and this class takes ownership over the pointer.
	//! Furtheremore if an equivalent potential already exists in the list, it will be removed.
	void insert(potential_base * p);
	~potential_list_t();
	//! Calculate u potential and f force
	//! \Param u potential output
	//! \Param f force output
	//! \Param r position input
	void eval(real_type & u,vector_array_type & f,const vector_array_type & r) const;
};

//! Potential list type.
//! It calculates the total potential, total force and the parameter derivatives
struct potential_fit_list_t : potential_list_t
{
	params_t params;
	void peval(real_type & u,vectorx_type & dp,const vectorx_type &  p,const vector_array_type & r);
	void get_parameter(vectorx_type & p);
};

//! A group_t class that contains labelled atom index group.
struct group_t
{
	std::map<std::string,std::set<atom_index> > data;
	void add(const std::string & label,atom_index i);
	void add(const std::string & label,const std::set<atom_index> & i_set);
	bool exist(const std::string & label) const;
	const std::set<atom_index> & operator[](const std::string & label) const;
};

struct topology_t
{
	std::set<std::pair<atom_index,atom_index> > data;

	void connect(atom_index i,atom_index j);
	bool connected(atom_index i,atom_index j) const;
	bool path(atom_index i,atom_index j) const;
	bool path(atom_index i,atom_index j,atom_index k) const;
	bool path(atom_index i,atom_index j,atom_index k,atom_index l) const;
};

struct position_t : vector_array_type
{
	position_t() {}
	position_t(size_t n) : vector_array_type(n) {}
};

struct velocity_t : vector_array_type
{
	velocity_t() {}
	velocity_t(size_t n) : vector_array_type(n) {}
};
struct mass_t : real_array_type
{
	mass_t() {}
	mass_t(size_t n) : real_array_type(n) {}
};

real_type kinetic_energy(const mass_t & mass,const velocity_t & velocity);

struct charge_t : real_array_type
{
	charge_t() {}
	charge_t(size_t n) : real_array_type(n) {}
};


struct constrain_t : std::vector<bool>
{
};

struct label_t : std::vector<std::string>
{
};

struct unitcell_t : matrix_type
{
};


//! List of all atoms and their properties. Assumed that all contained vector has same length.
struct atom_list_t
{
	position_t position;
	velocity_t velocity;
	mass_t mass;
	charge_t charge;
	label_t label;
	constrain_t fixed;
};

struct structure_t
{
	topology_t topology;
	group_t group;
	potential_list_t potential_list;
	unitcell_t unitcell;
	atom_list_t atom_list;
};

#endif // STRUCTURE_H

